/**
 * Created by macos on 14/11/5.
 */

var checksum = require('../checksum'),
  secret = require('../secret'),
  messageQ = require('../message-q');

(function () {

  var root = this;
  var redisClient = Redis.client();

  /**
   * 校验设备编码是否合法
   * @param sessionId
   * @param uuid
   * @param next
   */
  function validateUUID(sessionId, uuid, next) {

    Device.findOne({
      uuid: uuid
    })
      .exec(function (err, result) {
        if (err) {
          return next(err);
        } else {
          if (_.has(result, 'id')) {
            return next(null, sessionId, result);
          } else {
            return next('uuid not found:' + uuid);
          }
        }
      });
  }

  /**
   * 生成公钥、密钥
   * @param sessionId
   * @param device
   * @param next
   */
  function updateSecretInSession(sessionId, device, next) {

    var pubKey = secret.pubKey();
    var uuidBuffer = new Buffer(device.uuid, 'hex');
    var secretKey = secret.secretKey(uuidBuffer, new Buffer(pubKey, 'hex'));

    redisClient.keys(sessionId, function (err, value) {
      if (value.length > 0) {
        redisClient.hmset(sessionId, 'pubKey', pubKey);
        redisClient.hmset(sessionId, 'secretKey', secretKey);

        var result = {};
        result.content = pubKey;

        next(null, result);
      } else {
        next('session not found:' + sessionId)
      }
    });

  }

  /**
   * 定义登录的消息协议解析
   * @type {{event: string, type: number, content: content, checksum: checksum}}
   */
  var protocol = {
    event: 'faaf', //必须放在第一位，且必须是转换成16进制的字符串
    type: 1,
    content: function (msg, offset, buf, next) {
      var type = msg.type;

      if (type === '00') { //接受认证请求，获取UUID
        var end = offset + 16;
        var uuidBuffer = buf.slice(offset, end)
        var uuid = uuidBuffer.toString('hex');
        msg.uuid = uuid.toUpperCase();
        offset = end;

        return next(null, msg, offset, buf);

      } else if (type === '01') { //获取认证密码
        var end = offset + 2;
        var secretKeyBuffer = buf.slice(offset, end);
        msg.secretKey = secretKeyBuffer.toString('hex');
        offset = end;

        return next(null, msg, offset, buf);

      } else {
        return next('error type', msg);
      }
    },
    chksum: function (msg, offset, buf, next) { //最后一个对象的offset必须等于buf的长度
      msg.checksum = checksum.checksum(buf);
      if (checksum.validate(buf, msg.checksum)) {
        offset = offset + 1;
        return next(null, msg, offset, buf);
      } else {
        return next('error checksum', msg);
      }
    }
  };

  /**
   * 登录协议
   * @param server
   * @constructor
   */
  function Login(server) {

    sails.log.info('onMessage:', protocol);
    server.onMessage(protocol, function (err, msg, res) {

      if (err) {
        sails.log.error(err);
        res.destroy();
        return;
      }
      sails.log.debug('msg:', msg);

      if (res.isConnected) {
        if (msg.type === '00') { // 登录的第一步，接受客户端的设备号，返回公钥
          async.waterfall([
            async.apply(validateUUID, res.id, msg.uuid),
            updateSecretInSession
          ], function (err, result) {

            if (err) {
              sails.log.error(err);
              res.writeHex('affa0200ab');
              res.destroy();
              return;
            }

            redisClient.hmset(res.id, 'uuid', msg.uuid);
            redisClient.hgetall(res.id, function (err, session) {
              sails.log.debug('session after Login:', session);
            });

            result = {
              event: 'affa',
              type: '01',
              content: result.content
            };

            res.writeObj(result, function (hexStr) {
              var buf = new Buffer(hexStr, 'hex');
              var checksumStr = checksum.checksum(buf, 0, buf.length);
              hexStr = hexStr + checksumStr;
              return hexStr;
            });

          });

        } else if (msg.type === '01') { // 登录的第二步，接受客户端的密钥，返回认证结果

          redisClient.hgetall(res.id, function (err, session) {

            if (session.secretKey === msg.secretKey) { //TCP客户端登录成功
              //标识认证状态
              redisClient.hmset(res.id, 'isAuthenticated', 1);

              //回复认证结果
              res.writeHex('affa0201ac');

              //开启TCP客户端的消息订阅
              var channel = 'channel:' + session.uuid;
              messageQ.addChannel(channel);
              server.emit('authenticated', channel, res);

              //补发未发送的历史消息
              messageQ.sendHistoryRetry(session, res);

            } else {
              sails.log.error('error secret key:', msg.secretKey);
              res.writeHex('affa0200ab');
              res.destroy();
              return;
            }

          });

        } else {
          sails.log.error('error type:', msg.type);
          res.writeHex('affa0200ab');
          res.destroy();
          return;
        }
      }
    });

  }

  module.exports = {
    runProtocol: function runProtocol(server) {
      return new Login(server);
    }
  };

})()